#ifndef XGE_XTASK_H_
#define XGE_XTASK_H_
#include "xge_common_config.h"
#include "xthread_delegate.h"
#include "xassert.h"
#include "xbase_common.h"

// task classification 
// task can be classified basically as 2 type 
// Local task : running on the local thread ( MainThread )
// Remote task: running on the remote thread( BackThread )
// however, this is also the base 
// we also have more detail classification :
// 1. PriorityTask
//    this task has been assigned a priority , so it will be executed as priority order
//    it has be sticked to using PriorityQueue ( detail in worker queue implementation )
// 2  KillableTask
//    this task can be killed , pay attention : PriorityTask is also KillableTask
// 3. CommonTask
//    this task has no specification , it run in double_queue_worker_queue
//    not in PriorityQueue task queue
// detail information is in queue implementation file



namespace xge{
  class CommonTask;
  class KillableTask;
  class PriorityTask;
namespace xge_internal{
  // A common task definition
  // task is an atomic runnable unit , namely the code associated with its runnable code.
  // A task can have many different status , generally it have status list below :
  // 1. Waiting , this means the task is in the thread back queue or in 
  // the local queue to wait the thread to run it
  // 2. Locking , this means the task has been locked by the back thread , 
  // so this status may never existed on the
  // local_task
  // 3. Running, this means the task is running now , getting the cpu time to do its job
  // 4. Release , this means the task is running over, definitely you can get the task back
  // 5. Time out, this task has been waiting too long 
  // time and can not get the time to running the task now 
  // this xtask should never be derived by other specified task directly 
  // it is the internal task 

  class Task {
  public:
    // Join this task , if this task is a remote task , the join operation
    // will wait until the task status set to released or the time elapse "ms"
    // expired , when the time elapse expire , the task set to release it
    // will return true , otherwise false , if a local task call this
    // function , it will generate error
    // Join only return when the target task status is RELEASE
    bool Join();
    // Join this task , if this task is a remote task , the join operation
    // will wait until the task status set to released or the time elapse "ms"
    // expired , when the time elapse expire , the task set to release it
    // will return true , otherwise false , if a local task call this
    // function , it will generate error 
    // Join only return when the target task status is RELEASE
    const TripleResult Join( int ms );
    // Derive from this class and rewrite this function
    // inside this function will perform the execution stuff
    // of this task 
    virtual void Execute() = 0;
    // virtual dtor
    virtual ~Task() {
      XASSERT_BINARY(NEQ,INT,task_status_,TASK_STATUS_RUNNING);
    }
    // Bind type
    // a task can be remote task
    // which will run in the back thread so it is a asynchronized
    // also a task can be assigned as local task which will
    // run in this thread ( local thread )
    // using the xge_common_header macro REMOTE_BINDING and LOCAL_BINDING
    // Get the task type 
    // it is used as debug routine 
    int bind_type() const {
      return bind_type_;
    }
    // Task status
    enum {
      TASK_STATUS_WAITING = 0 , // Waiting for the dispatcher to call this task
      TASK_STATUS_LOCKING = 1 , // Now it is locked by the DoubleQueued or worker queue , it should never be reached by some type of queue
      TASK_STATUS_RUNNING = 2 , // Now it is running 
      TASK_STATUS_RELEASE = 3   // Now it is discarding by the thread
    };
    // Down case type
    // Here we just use a trick to do the
    // nest type down cast , we need to
    // do the specialization so we have
    // to make this as different type .
    // namely class or struct .
    enum{
      DOWNCAST_COMMON_TASK   =1, // common task
      DOWNCAST_PRIORITY_TASK =2, // priority task
      DOWNCAST_KILLABLE_TASK =3, // killable task
      DOWNCAST_USER_TASK     =4  // user task ( if it is not the task above , use this )
    }; 
    // Task status returning value
    int task_status() const {
      return task_status_;
    }

    void set_task_status( int status ) {
      task_status_ = status;
    }

    int downcast_type() const {
      return downcast_type_;
    }

    Task( int dc_type , int bind_type ) : 
      bind_type_(bind_type), 
      task_status_(TASK_STATUS_WAITING) ,
      downcast_type_(dc_type) {
        // checking the type is inside the enumeration 
        XASSERT(bind_type_ >= MIN_TASK_BINDING_VALUE || bind_type_ == MAX_TASK_BINDING_VALUE );
        XASSERT(downcast_type_>=DOWNCAST_COMMON_TASK || downcast_type_ <= DOWNCAST_USER_TASK);
      }
  private:
      // get some specific value here 
      template< typename DowncastClass > struct TypeValue {
        static const size_t Value = DOWNCAST_USER_TASK;
      };
      template<>struct TypeValue<CommonTask> {
        static const size_t Value = DOWNCAST_COMMON_TASK;
      };
      template<>struct TypeValue<KillableTask> {
        static const size_t Value = DOWNCAST_KILLABLE_TASK;
      };
      template<>struct TypeValue<PriorityTask> {
        static const size_t Value = DOWNCAST_PRIORITY_TASK;
      };
  public:
    // A tiny wrapper for safe cast
    // Anyway , it is so called safe , since if you want to make
    // it unsafe , I have no way to protect it since C++ do not
    // have meta information and do not provide RTTI 
      template< typename ClassType > ClassType* DownCast() const {
        XASSERT_SAY( this->downcast_type() == TypeValue<ClassType>::Value ,_xT("%d,%d"),this->downcast_type(),TypeValue<ClassType>::Value);
        return (ClassType*)(this);
      }
  private:
    // Task type indicator
    int bind_type_;
    // Task status
    volatile int task_status_;
    // Task type
    const int downcast_type_;

  };

}//namespace xge_internal

  // task ptr 
  typedef xge_internal::SharedPtr<xge_internal::Task,xge_internal::DefaultDestructor<xge_internal::Task> > TaskPtr;

} //namespace xge
#endif// XGE_XTASK_H_